#include "xparameters.h" // 包含各类宏定义
#include "xil_printf.h" // 串口输出函数xil_printf
#include "xgpio.h" // GPIO 器件头文件
#include "xintc.h" // INTC 中断头文件
#include "sleep.h" // 延时器 头文件
#include "xil_exception.h" // 中断异常 头文件
#include "xuartlite.h" // 串口 器件头文件
#include "xuartlite_l.h" // 串口 器件头文件
#include "xtmrctr.h" // 定时器 头文件
#include "xtmrctr_i.h" // 定时器 头文件
#include "xtmrctr_l.h" // 定时器 头文件
#include "breath_led_ip.h" // LED IP 头文件
// #include "xil_io.h"

// GPIO KEY
#define KEY_DEVICE_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define KEY_CHANNEL 1

// UART
#define UART_DEVICE_ID XPAR_AXI_UARTLITE_0_DEVICE_ID

// TIMER
#define TIMER0_DEVICE_ID XPAR_AXI_TIMER_0_DEVICE_ID

// INTC
#define INTC_DEVICE_ID XPAR_AXI_INTC_0_DEVICE_ID // 中断控制器ID
#define INTC_EXCEP_DEVICE_ID XIL_EXCEPTION_ID_INT // 中断控制器异常ID
#define AXI_GPIO_INTR_ID XPAR_INTC_0_GPIO_0_VEC_ID // 连接GPIO中断源与中断控制器
#define AXI_UART_INTR_ID XPAR_INTC_0_UARTLITE_0_VEC_ID // 连接串口中断源与中断控制器
#define AXI_TIMER0_INTR_ID XPAR_INTC_0_TMRCTR_0_VEC_ID // 连接定时器中断源与中断控制器

#define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S01_AXI_BASEADDR // LED IP基地址
#define LED_IP_REG0 BREATH_LED_IP_S01_AXI_SLV_REG0_OFFSET // LED IP 寄存器地址0
#define LED_IP_REG1 BREATH_LED_IP_S01_AXI_SLV_REG1_OFFSET // LED IP 寄存器地址1

XIntc Intc;
XGpio KeyGpio;
XUartLite Uart;
XTmrCtr Timer0;
volatile uint8_t key_intr_flag = 0;
void GpioHandler(void *CallBackRef);
void UartHandler(void *CallBackRef);
void TimerIntrHandler(void *CallBackRef);
int main(void) {
	// GPIO 器件初始化
	XGpio_Initialize(&KeyGpio, KEY_DEVICE_ID);

	// 串口 器件初始化
	XUartLite_Initialize(&Uart, UART_DEVICE_ID);
	print("USART IS OK!\n"); // 串口发送测试

	// TIMR0 器件初始化
	XTmrCtr_Initialize(&Timer0, TIMER0_DEVICE_ID);
	// 第二个参数为定时器序号  定时器1为0，定时器2为1.第三个参数为模式选项，所有选项可以看xtmrctr.h文件
	XTmrCtr_SetOptions(&Timer0, 0,
	XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION);
	// 设置重装载值
	XTmrCtr_SetResetValue(&Timer0, 0, 50000000);
	// 设置回调函数函数名（自己设定）
	XTmrCtr_SetHandler(&Timer0, (XTmrCtr_Handler) TimerIntrHandler, &Timer0);
	// 开启定时器
	XTmrCtr_Start(&Timer0, 0);

	// 中断控制器 器件初始化
	XIntc_Initialize(&Intc, INTC_DEVICE_ID);
	// 设置并打开中断异常处理功能
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(INTC_EXCEP_DEVICE_ID,
			(Xil_ExceptionHandler) XIntc_InterruptHandler, &Intc);
	Xil_ExceptionEnable();

	// 连接中断源与中断控制器
	XIntc_Connect(&Intc, AXI_GPIO_INTR_ID, (XInterruptHandler) GpioHandler,
			&KeyGpio); // GPIO中断源与中断控制器相连接
	XIntc_Connect(&Intc, AXI_UART_INTR_ID, (XInterruptHandler) UartHandler,
			&Uart); // UART中断源与中断控制器相连接
	XIntc_Connect(&Intc, AXI_TIMER0_INTR_ID,
			(XInterruptHandler) XTmrCtr_InterruptHandler, &Timer0); // TIMER0中断源与中断控制器相连接
	XGpio_InterruptEnable(&KeyGpio, 1); // GPIO中断源使能
	XGpio_InterruptGlobalEnable(&KeyGpio); // GPIO中断源全局使能
	XUartLite_EnableInterrupt(&Uart); // 串口中断使能

	// 使能并启动中断控制器
	XIntc_Enable(&Intc, AXI_GPIO_INTR_ID); // 中断控制器使能
	XIntc_Enable(&Intc, AXI_UART_INTR_ID); // 中断控制器使能
	XIntc_Enable(&Intc, AXI_TIMER0_INTR_ID); // 中断控制器使能
	XIntc_Start(&Intc, XIN_REAL_MODE); // 中断控制器开始
    
    // 开启呼吸灯
    BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, LED_IP_REG0, 0X00000001);
    BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, LED_IP_REG1, 0X80000000);
	while (1) {

	}
	return 0;
}
void GpioHandler(void *CallBackRef) {
	XGpio *GpioPtr = (XGpio *) CallBackRef;
	xil_printf("GPIO interrupt\n");
}
void UartHandler(void *CallBackRef) {
	XUartLite *UartPtr = (XUartLite *) CallBackRef;
	uint32_t isr_status = XUartLite_ReadReg(UartPtr->RegBaseAddress,
			XUL_STATUS_REG_OFFSET);
	if (isr_status & XUL_SR_RX_FIFO_VALID_DATA) {
		uint8_t ReadData = XUartLite_ReadReg(UartPtr->RegBaseAddress,
				XUL_RX_FIFO_OFFSET);
		XUartLite_WriteReg(UartPtr->RegBaseAddress, XUL_TX_FIFO_OFFSET,
				ReadData);
	}
}

void TimerIntrHandler(void *CallBackRef) {
	XTmrCtr *TimerPtr = (XTmrCtr *) CallBackRef;
	xil_printf("TIMES UP!\n");
}
